// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#include <nebula/types/fundamental.h>
#include <turbo/log/logging.h>
#include <nebula/types/type_traits.h>

namespace nebula {


    std::string type_id_fingerprint(const DataType &type) {
        auto c = static_cast<int>(type.id()) + 'A';
        DKCHECK_GE(c, 0);
        DKCHECK_LT(c, 128);  // Unlikely to happen any soon
        // Prefix with an unusual character in order to disambiguate
        std::string s{'@', static_cast<char>(c)};
        return s;
    }

    // ----------------------------------------------------------------------
    // Run-end encoded type

    RunEndEncodedType::RunEndEncodedType(std::shared_ptr<DataType> run_end_type,
                                         std::shared_ptr<DataType> value_type)
            : NestedType(Type::RUN_END_ENCODED) {
        DKCHECK(RunEndTypeValid(*run_end_type));
        children_ = {std::make_shared<Field>("run_ends", std::move(run_end_type), false),
                     std::make_shared<Field>("values", std::move(value_type), true)};
    }

    RunEndEncodedType::~RunEndEncodedType() = default;

    std::string RunEndEncodedType::to_string(bool show_metadata) const {
        std::stringstream s;
        s << name() << "<run_ends: " << run_end_type()->to_string(show_metadata)
          << ", values: " << get_value_type()->to_string(show_metadata) << ">";
        return s.str();
    }

    bool RunEndEncodedType::RunEndTypeValid(const DataType &run_end_type) {
        return is_run_end_type(run_end_type.id());
    }


    std::string RunEndEncodedType::compute_fingerprint() const {
        std::stringstream ss;
        ss << type_id_fingerprint(*this) << "{";
        ss << run_end_type()->fingerprint() << ";";
        ss << get_value_type()->fingerprint() << ";";
        ss << "}";
        return ss.str();
    }

}  // namespace nebula
